#include "ml307_app.h"

#if (_NETWOK_MODLE_TYPE_ == _ML307R_MODLE_) && (_NETWOK_FUNCTION_ENABLE_)

static Ml307BitStatus_t Ml307BitStatus = {0};
static Ml307HardwareAttributes_t Ml307HardwareAttributes = {0};

void Ml307CommunicationsInitialization(void)
{
  memset(&Ml307BitStatus, 0, sizeof(Ml307BitStatus_t));
  Ml307BitStatus.StepsOfSending = ML307_COMMECT_TEST;
}

void Ml307FilterKeywords(const void *pMessagePacket, uint16_t *pMessageSize)
{
}

bool Ml307BuildSelfTestMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
  bool MessageConstructionState = false;

  if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
  {
    switch (Ml307BitStatus.StepsOfSending)
    {
    case ML307_CLOSE_COMMADN_RETURN:
    {
      MessageConstructionState = ML307BuildCloseCommandReturnMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_VERSION_NUMBER:
    {
      MessageConstructionState = Ml307BuildGetFirmwareVersionMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_MANUFACTURER_INFORMATION:
    {
      MessageConstructionState = Ml307BuildQueryModuleManufacturerInformationMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_IMEI_CODE:
    {
      MessageConstructionState = Ml307BuildGetIMEIMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_CARD_INSERTED_STATUS:
    {
      MessageConstructionState = ML307BuildCheckIfTheSimCardIsRecognizedMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENDING_LONG_DELAY;
    }
    break;

    case ML307_GET_IMSI_CODE:
    {
      MessageConstructionState = Ml307BuildGetIMSIMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_CARD_ICCID_NUMBER:
    {
      MessageConstructionState = Ml307BuildGetIccidMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_SIGNAL_STRENGTH:
    {
      MessageConstructionState = Ml307BuildCheckSignalStrengthMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    default:
    {
      MessageConstructionState = Ml307BuildCommectTestMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;
    }
  }

  return MessageConstructionState;
}

bool Ml307BuildInitiateNetAttachmentMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
  bool MessageConstructionState = false;

  if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
  {
    switch (Ml307BitStatus.StepsOfSending)
    {
    case ML307_CLOSE_COMMADN_RETURN:
    {
      MessageConstructionState = ML307BuildCloseCommandReturnMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_CARD_INSERTED_STATUS:
    {
      MessageConstructionState = ML307BuildCheckIfTheSimCardIsRecognizedMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENDING_LONG_DELAY;
    }
    break;

    case ML307_GET_SIGNAL_STRENGTH:
    {
      MessageConstructionState = Ml307BuildCheckSignalStrengthMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_NETWORK_REGISTER_STATUS:
    {
      MessageConstructionState = Ml307BuildCheckIfTheNetworkIsRegisteredMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_NETWORK_ATTACHMENT_STATUS:
    {
      MessageConstructionState = Ml307BuildCheckIfTheNtworkIsAttachedMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_NETWORK_OPERATION:
    {
      MessageConstructionState = Ml307BuildGetNetworkOperatorMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_SET_NETWORK_OPERATION:
    {
      uint8_t Operator = Ml307GetNetworkOperator();

      MessageConstructionState = Ml307BuildSelectNetworkOperatorMessage(pMessageOut, pSizeOut, Operator);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_CONFIG_DNS_SERVER:
    {
      uint8_t DnsServerIpAddress[ML307_SERVER_ADDRESS_LENGTH] = {0};

      Ml307GetDnsServerAddress(DnsServerIpAddress);
      MessageConstructionState = Ml307BuildDnsConfigurationMessage(pMessageOut, pSizeOut, DnsServerIpAddress, ML307_DNS_ALTERNATIVE_IP_ADDRESS);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_DNS_SERVER_START:
    {
      char DomainName[ML307_MQTT_DOMAIN_NAME_LENGTH] = {0};

      Ml307GetNetworkDomianName(DomainName);
      MessageConstructionState = Ml307BuildStartDnsDomainNameResolutionMessage(pMessageOut, pSizeOut, DomainName);
      *pResponseTimeOut = ML307_MESSAGE_SENDING_LONG_DELAY;
    }
    break;

    case ML307_OPEN_TCP_SERVER:
    {
      uint16_t ConnectPort = Ml307GetServerConnectPort();

      MessageConstructionState = Ml307BuildTcpOpenMessage(pMessageOut, pSizeOut, Ml307BitStatus.HostIpAddress, ConnectPort);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_GET_TCP_CONNECT_STATUS:
    {
      MessageConstructionState = Ml307BuildTcpGetConnectStatusMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_TCP_SWITCH_TRANSMISSION_MODE:
    {
      MessageConstructionState = Ml307BuildTcpSwitchToTransparentModeMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_CLOSE_MQTT_SERVER:
    {
      MessageConstructionState = Ml307BuildMqttDiscMessage(pMessageOut, pSizeOut, 0);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;

    case ML307_OPEN_MQTT_SERVER:
    {
      uint16_t Port = 0;
      char UserName[ML307_MQTT_USER_NAME_LENGTH] = {0}, DomainName[ML307_MQTT_DOMAIN_NAME_LENGTH] = {0}, Password[ML307_MQTT_PASSWORD_LENGTH] = {0};

      Ml307GetMqttPassword(Password);
      Ml307GetMqttUserName(UserName);
      Port = Ml307GetServerConnectPort();
      Ml307GetNetworkDomianName(DomainName);

      MessageConstructionState = Ml307BuildMqttConnectMessage(pMessageOut, pSizeOut, 0, DomainName, Port, UserName, Password);
      *pResponseTimeOut = ML307_MESSAGE_SENDING_LONG_DELAY;
    }
    break;

    case ML307_SUBSCRIBE_MQTT_TOPICS:
    {
      uint16_t NumberOfTopics = 0;
      char Topics[ML307_MQTT_TOPIC_LENGTH] = {0};
      uint8_t MacAddr[ML307_DEVICE_MAC_ADDRESS_CODING_LENGTH] = {0};

      Ml307GetDeviceMacAddress(MacAddr);
      Ml307GetMqttPublishTopic(Topics);
      NumberOfTopics = strlen(Topics);
      sprintf(&Topics[NumberOfTopics], "/%02x%02x%02x%02x%02x%02x", MacAddr[0], MacAddr[1], MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5]);

      Ml307BuildMqttSubscribeToTopicsMessage(pMessageOut, pSizeOut, 0, Topics);
      *pResponseTimeOut = ML307_MESSAGE_SENDING_LONG_DELAY;
    }
    break;

    default:
    {
      MessageConstructionState = Ml307BuildCommectTestMessage(pMessageOut, pSizeOut);
      *pResponseTimeOut = ML307_MESSAGE_SENGING_RATED_TIME;
    }
    break;
    }
  }

  return MessageConstructionState;
}

uint8_t Ml307ParsingSelfTestMessage(const void *pDataIn)
{
  uint8_t ParsingResults = ML307_EXECUTE_ERROR;
  Ml307MessageParsingResult_t ParsingState = ML307_PARSING_ERROR;

  if (pDataIn != NULL)
  {
    switch (Ml307BitStatus.StepsOfSending)
    {
    case ML307_COMMECT_TEST:
    {
      ParsingState = Ml307ParsingConnectTestMessage(pDataIn);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_CLOSE_COMMADN_RETURN;
      }
    }
    break;

    case ML307_CLOSE_COMMADN_RETURN:
    {
      ParsingState = Ml307ParsingCloseCommandReturnMessage(pDataIn);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_VERSION_NUMBER;
      }
    }
    break;

    case ML307_GET_VERSION_NUMBER:
    {
      ParsingState = Ml307ParsingGetFirmwareVersionMessage(pDataIn, Ml307HardwareAttributes.VersionNumber, ML307_NUMBER_OF_VERSION);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_MANUFACTURER_INFORMATION;
      }
    }
    break;

    case ML307_GET_MANUFACTURER_INFORMATION:
    {
      ParsingState = Ml307ParsingQueryModuleManufacturerInformationMessage(pDataIn, NULL, 0);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_IMEI_CODE;
      }
    }
    break;

    case ML307_GET_IMEI_CODE:
    {
      ParsingState = Ml307ParsingGetIMEIMessage(pDataIn, Ml307HardwareAttributes.IMEICode, ML307_NUMBER_OF_SERIAL_NUMBER);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_CARD_INSERTED_STATUS;
      }
    }
    break;

    case ML307_GET_CARD_INSERTED_STATUS:
    {
      ParsingResults = ML307_EXECUTE_RETRY;

      ParsingState = Ml307ParsingCheckIfTheSimCardIsRecognizedMessage(pDataIn);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_IMSI_CODE;
      }
    }
    break;

    case ML307_GET_IMSI_CODE:
    {
      ParsingState = Ml307ParsingGetIMSIMessage(pDataIn, Ml307HardwareAttributes.IMSICode, ML307_NUMBER_OF_VERSION);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_CARD_ICCID_NUMBER;
      }
    }
    break;

    case ML307_GET_CARD_ICCID_NUMBER:
    {
      ParsingState = Ml307ParsingGetIccidMessage(pDataIn, Ml307HardwareAttributes.CardSerialNumber, ML307_NUMBER_OF_SERIAL_NUMBER);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_SUCCESS;
        Ml307BitStatus.StepsOfSending = ML307_GET_SIGNAL_STRENGTH;
      }
    }
    break;

    case ML307_GET_SIGNAL_STRENGTH:
    {
      ParsingResults = ML307_EXECUTE_RETRY;

      ParsingState = Ml307ParsingCheckSignalStrengthMessage(pDataIn, &Ml307HardwareAttributes.Rssi);
      if (ParsingState == ML307_PARSING_SUCCESS)
      {
        ParsingResults = ML307_EXECUTE_OVER;
        Ml307BitStatus.StepsOfSending = ML307_ALL_COMMAND_EXECUTED;
      }
    }
    break;

    default:
      break;
    }
  }

  return ParsingResults;
}

uint8_t Ml307ParsingInitiateNetAttachmentMessage(const void *pDataIn)
{
  uint8_t ParsingResults = ML307_EXECUTE_ERROR;
  Ml307MessageParsingResult_t ParsingState = ML307_PARSING_ERROR;

  switch (Ml307BitStatus.StepsOfSending)
  {
  case ML307_COMMECT_TEST:
  {
    ParsingState = Ml307ParsingConnectTestMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_CLOSE_COMMADN_RETURN;
    }
  }
  break;

  case ML307_CLOSE_COMMADN_RETURN:
  {
    ParsingState = Ml307ParsingCloseCommandReturnMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_GET_CARD_INSERTED_STATUS;
    }
  }
  break;

  case ML307_GET_CARD_INSERTED_STATUS:
  {
    ParsingResults = ML307_EXECUTE_RETRY;

    ParsingState = Ml307ParsingCheckIfTheSimCardIsRecognizedMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_GET_SIGNAL_STRENGTH;
    }
  }
  break;

  case ML307_GET_SIGNAL_STRENGTH:
  {
    ParsingResults = ML307_EXECUTE_RETRY;

    ParsingState = Ml307ParsingCheckSignalStrengthMessage(pDataIn, &Ml307HardwareAttributes.Rssi);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_GET_NETWORK_REGISTER_STATUS;
    }
  }
  break;

  case ML307_GET_NETWORK_REGISTER_STATUS:
  {
    ParsingResults = ML307_EXECUTE_RETRY;

    ParsingState = Ml307ParsingCheckIfTheNetworkIsRegisteredMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_GET_NETWORK_ATTACHMENT_STATUS;
    }
  }
  break;

  case ML307_GET_NETWORK_ATTACHMENT_STATUS:
  {
    ParsingResults = ML307_EXECUTE_RETRY;

    ParsingState = Ml307ParsingCheckIfTheNtworkIsAttachedMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;

#if _NETWORK_SERVICE_TYPE_ == _TCP_NETWORK_SERVICE_
#if _DNS_SERVICE_ENABLE_
      Ml307BitStatus.StepsOfSending = ML307_CONFIG_DNS_SERVER;
#else
      Ml307BitStatus.StepsOfSending = ML307_OPEN_TCP_SERVER;
      Ml307GetServerConnectAddress(Ml307BitStatus.HostIpAddress);
#endif

#elif _NETWORK_SERVICE_TYPE_ == _MQTT_NETWORK_SERVICE_
      Ml307BitStatus.StepsOfSending = ML307_CLOSE_MQTT_SERVER;
#endif
    }
  }
  break;

  case ML307_CONFIG_DNS_SERVER:
  {
    ParsingState = Ml307ParsingDnsConfigurationMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_DNS_SERVER_START;
    }
  }
  break;

  case ML307_DNS_SERVER_START:
  {
    ParsingState = Ml307ParsingStartDnsDomainNameResolutionMessage(pDataIn, Ml307BitStatus.HostIpAddress);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_OPEN_TCP_SERVER;
    }
    else if (ParsingState == ML307_PARSING_NO_KEYWORD_FOUND)
    {
      ParsingResults = ML307_EXECUTE_WAIT;
    }
  }
  break;

  case ML307_OPEN_TCP_SERVER:
  {
    ParsingState = Ml307ParsingTcpOpenMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_GET_TCP_CONNECT_STATUS;
    }
    else if (ParsingState == ML307_PARSING_NO_KEYWORD_FOUND)
    {
      ParsingResults = ML307_EXECUTE_WAIT;
    }
  }
  break;

  case ML307_GET_TCP_CONNECT_STATUS:
  {
    ParsingResults = ML307_EXECUTE_RETRY;

    ParsingState = Ml307ParsingGetTcpConnectStatusMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_TCP_SWITCH_TRANSMISSION_MODE;
    }
  }
  break;

  case ML307_TCP_SWITCH_TRANSMISSION_MODE:
  {
    ParsingState = Ml307ParsingTcpSwitchToTransparentModeMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_OVER;
      Ml307BitStatus.StepsOfSending = ML307_ALL_COMMAND_EXECUTED;
    }
  }
  break;

  case ML307_CLOSE_MQTT_SERVER:
  {
    ParsingState = Ml307ParsingMqttDiscMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_OPEN_MQTT_SERVER;
    }
  }
  break;

  case ML307_OPEN_MQTT_SERVER:
  {
    ParsingState = Ml307ParsingMqttConnectMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_SUCCESS;
      Ml307BitStatus.StepsOfSending = ML307_SUBSCRIBE_MQTT_TOPICS;
    }
  }
  break;

  case ML307_SUBSCRIBE_MQTT_TOPICS:
  {
    ParsingResults = ML307_EXECUTE_RETRY;

    ParsingState = Ml307ParsingMqttSubscribeToTopicsMessage(pDataIn);
    if (ParsingState == ML307_PARSING_SUCCESS)
    {
      ParsingResults = ML307_EXECUTE_OVER;
      Ml307BitStatus.StepsOfSending = ML307_ALL_COMMAND_EXECUTED;
    }
  }
  break;

  default:
    break;
  }

  return ParsingResults;
}

void Ml307GetFirmwareVersion(char *pVersionOut)
{
  if (pVersionOut != NULL)
  {
    strcpy(pVersionOut, Ml307HardwareAttributes.VersionNumber);
  }
}

void Ml307GetImeiCode(char *pImeiCodeOut)
{
  if (pImeiCodeOut != NULL)
  {
    strcpy(pImeiCodeOut, Ml307HardwareAttributes.IMEICode);
  }
}

void Ml307GetImsiCode(char *pImsiCodeOut)
{
  if (pImsiCodeOut != NULL)
  {
    strcpy(pImsiCodeOut, Ml307HardwareAttributes.IMSICode);
  }
}

void Ml307GetSimIccidCode(char *pIccidOut)
{
  if (pIccidOut != NULL)
  {
    strcpy(pIccidOut, Ml307HardwareAttributes.CardSerialNumber);
  }
}

uint8_t Ml307GetSignalStrength(void)
{
  return Ml307HardwareAttributes.Rssi;
}

void Ml307SendDataToServer(const uint8_t *pDataIn, uint16_t DataSize, bool (*pUartSend)(const uint8_t *, uint16_t))
{
  if ((pDataIn != NULL) && (pUartSend != NULL))
  {
    if ((DataSize > 0) && (DataSize <= ML307_MAX_RECEIVE_DATA_LENGTH))
    {
#if _NETWORK_SERVICE_TYPE_ == _TCP_NETWORK_SERVICE_
      pUartSend(pDataIn, DataSize);

#elif _NETWORK_SERVICE_TYPE_ == _MQTT_NETWORK_SERVICE_
      uint16_t PublishDataSize = 0;
      char ToTopics[ML307_MQTT_TOPIC_LENGTH] = {0};
      uint8_t MessageDataPacket[ML307_MAX_RECEIVE_DATA_LENGTH] = {0};

      Ml307GetMqttSubscribeTopic(ToTopics);
      Ml307BuildMqttPublishMessage(MessageDataPacket, &PublishDataSize, 0, ToTopics, DataSize);
      pUartSend(MessageDataPacket, PublishDataSize);
      Ml307DelayMs(ML307_WAIT_DEVICE_ACK_TIME);

      memset(MessageDataPacket, 0, ML307_MAX_RECEIVE_DATA_LENGTH);
      memcpy(MessageDataPacket, pDataIn, DataSize);

      pUartSend(MessageDataPacket, DataSize);
#endif
    }
  }
}

bool Ml307ParsingMqttTopicPushMessages(const void *pRxMessage, uint16_t MessageLenght)
{
#if _NETWORK_SERVICE_TYPE_ == _TCP_NETWORK_SERVICE_
  const uint8_t *pRxDataBuff = pRxMessage;

  if (pRxDataBuff != NULL)
  {
    Ml307ForwardIncomingData(pRxDataBuff, MessageLenght);
    return true;
  }

#elif _NETWORK_SERVICE_TYPE_ == _MQTT_NETWORK_SERVICE_
  uint16_t MessageDataSize = 0;
  uint8_t TempDataBuff[ML307_MAX_RECEIVE_DATA_LENGTH] = {0};

  if (Ml307ParsingPublishMessage(pRxMessage, TempDataBuff, &MessageDataSize) == true)
  {
    Ml307ForwardIncomingData(TempDataBuff, MessageDataSize);
    return true;
  }
#endif

  return false;
}

uint8_t Ml307ParsingIncomingMessageValidity(const void *pRxMessage, uint16_t MessageLenght)
{
  char *ParsingMessage = (char *)pRxMessage;
  uint8_t MessageType = ML307_RESPOND_ERROR, ConnectStatus = 0;

  if (pRxMessage != NULL)
  {
    if (MessageLenght > 0)
    {
#if _NETWORK_SERVICE_TYPE_ == _TCP_NETWORK_SERVICE_
      MessageType = ML307_RESPOND_HOST;

      if ((ParsingMessage[MessageLenght - 2] == '\r') && (ParsingMessage[MessageLenght - 1] == '\n'))
      {
        MessageType = ML307_RESPOND_AT;

        if (Ml307DetermineIfItIsTcpUrcEvent(pRxMessage) == true)
        {
          PRINT("[ml307]: tcp urc: ");

          if (Ml307DetermineMessageIsInformingNetworkDisconnectionState(pRxMessage) == true)
          {
            PRINT("\"disconnect\".\r\n");
            MessageType = ML307_RESPOND_DISCONNECT;
          }
          else
          {
            PRINT("\"other\".\r\n");
            MessageType = ML307_RESPOND_DEV_STATE;
          }
        }
      }

#elif _NETWORK_SERVICE_TYPE_ == _MQTT_NETWORK_SERVICE_
      MessageType = ML307_RESPOND_AT;

      if (Ml307DetermineIfItIsMqttUrcEvent(pRxMessage) == true)
      {
        PRINT("[ml307]: mqtt urc: ");

        if (Ml307DetermineMessageIsInformingNetworkConnectionState(pRxMessage, &ConnectStatus) == true)
        {
          PRINT("\"connect event\", status: %d.\r\n", ConnectStatus);

          if (ConnectStatus != ML307_MQTT_CONNECT_SUCCESS)
          {
            MessageType = ML307_RESPOND_DISCONNECT;
          }
        }
        else if (Ml307DetermineIfTheMessageIsServerPushData(pRxMessage) == true)
        {
          PRINT("\"publish\".\r\n");
          MessageType = ML307_RESPOND_HOST;
        }
        else
        {
          PRINT("\"other\".\r\n");
          MessageType = ML307_RESPOND_DEV_STATE;
        }
      }
#endif
    }
  }

  return MessageType;
}

#endif
